// Copyright (c) 2024 IndustrialTBB Framework
// Licensed under MIT License

#ifndef ITBB_MONITORING_TBB_PERFORMANCE_MONITOR_H_
#define ITBB_MONITORING_TBB_PERFORMANCE_MONITOR_H_

#include <oneapi/tbb.h>
#include <oneapi/tbb/concurrent_hash_map.h>
#include <oneapi/tbb/concurrent_vector.h>

#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include <string>
#include <vector>

#include "itbb/core/tbb_concurrent_containers.h"
#include "itbb/core/tbb_observer.h"

namespace itbb {
// 性能指标类型
enum class MetricType {
  kCounter,    // 计数器
  kGauge,      // 仪表
  kHistogram,  // 直方图
  kTimer,      // 计时器
  kRate        // 速率
};

// 性能指标数据点
struct MetricDataPoint {
  std::chrono::steady_clock::time_point timestamp;
  double value;
  std::string tags;  // 可选的标签信息

  MetricDataPoint(double v, const std::string& t = "")
      : timestamp(std::chrono::steady_clock::now()), value(v), tags(t) {}
};

// 性能指标统计信息
struct MetricStatistics {
  double min_value = std::numeric_limits<double>::max();
  double max_value = std::numeric_limits<double>::lowest();
  double sum_value = 0.0;
  double avg_value = 0.0;
  uint64_t count = 0;
  double std_deviation = 0.0;

  // 百分位数
  double p50 = 0.0;
  double p90 = 0.0;
  double p95 = 0.0;
  double p99 = 0.0;

  void Update(double value) {
    min_value = std::min(min_value, value);
    max_value = std::max(max_value, value);
    sum_value += value;
    count++;
    avg_value = sum_value / count;
  }
};

// TBB原生的性能指标
class TbbPerformanceMetric {
 public:
  TbbPerformanceMetric(const std::string& name, MetricType type)
      : name_(name), type_(type), data_points_() {}

  virtual ~TbbPerformanceMetric() = default;

  // 记录数据点
  void Record(double value, const std::string& tags = "") {
    data_points_.AddDataPoint(MetricDataPoint(value, tags));

    // 更新统计信息
    UpdateStatistics(value);
  }

  // 获取最新的N个数据点
  std::vector<MetricDataPoint> GetLatestData(size_t count = 100) const {
    return data_points_.GetLatestData(count);
  }

  // 获取指定时间范围内的数据
  std::vector<MetricDataPoint> GetDataInRange(
      std::chrono::steady_clock::time_point start,
      std::chrono::steady_clock::time_point end) const {
    return data_points_.GetDataInRange(start, end);
  }

  // 获取统计信息
  MetricStatistics GetStatistics() const {
    std::lock_guard<std::mutex> lock(stats_mutex_);
    return statistics_;
  }

  // 重置指标
  void Reset() {
    data_points_ = TbbTimeSeriesContainer<MetricDataPoint>(10000);

    std::lock_guard<std::mutex> lock(stats_mutex_);
    statistics_ = MetricStatistics{};
  }

  const std::string& GetName() const { return name_; }
  MetricType GetType() const { return type_; }

 protected:
  std::string name_;
  MetricType type_;
  TbbTimeSeriesContainer<MetricDataPoint> data_points_;

  mutable std::mutex stats_mutex_;
  MetricStatistics statistics_;

  void UpdateStatistics(double value) {
    std::lock_guard<std::mutex> lock(stats_mutex_);
    statistics_.Update(value);
  }
};

// 计数器指标
class TbbCounterMetric : public TbbPerformanceMetric {
 public:
  explicit TbbCounterMetric(const std::string& name)
      : TbbPerformanceMetric(name, MetricType::kCounter), counter_(0) {}

  void Increment(double delta = 1.0) {
    double new_value =
        counter_.fetch_add(delta, std::memory_order_relaxed) + delta;
    Record(new_value);
  }

  void Decrement(double delta = 1.0) {
    double new_value =
        counter_.fetch_sub(delta, std::memory_order_relaxed) - delta;
    Record(new_value);
  }

  double GetValue() const { return counter_.load(std::memory_order_acquire); }

  void SetValue(double value) {
    counter_.store(value, std::memory_order_release);
    Record(value);
  }

 private:
  std::atomic<double> counter_;
};

// 仪表指标
class TbbGaugeMetric : public TbbPerformanceMetric {
 public:
  explicit TbbGaugeMetric(const std::string& name)
      : TbbPerformanceMetric(name, MetricType::kGauge), gauge_(0) {}

  void SetValue(double value) {
    gauge_.store(value, std::memory_order_release);
    Record(value);
  }

  double GetValue() const { return gauge_.load(std::memory_order_acquire); }

 private:
  std::atomic<double> gauge_;
};

// 计时器指标
class TbbTimerMetric : public TbbPerformanceMetric {
 public:
  explicit TbbTimerMetric(const std::string& name)
      : TbbPerformanceMetric(name, MetricType::kTimer) {}

  // 计时器作用域类
  class TimerScope {
   public:
    explicit TimerScope(TbbTimerMetric& timer)
        : timer_(timer),
          start_time_(std::chrono::high_resolution_clock::now()) {}

    ~TimerScope() {
      auto end_time = std::chrono::high_resolution_clock::now();
      auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(
          end_time - start_time_);
      timer_.Record(static_cast<double>(duration.count()) /
                    1000000.0);  // 转换为毫秒
    }

   private:
    TbbTimerMetric& timer_;
    std::chrono::high_resolution_clock::time_point start_time_;
  };

  // 创建计时作用域
  TimerScope CreateScope() { return TimerScope(*this); }

  // 手动记录时间
  void RecordTime(std::chrono::nanoseconds duration) {
    Record(static_cast<double>(duration.count()) / 1000000.0);
  }
};

// 直方图指标
class TbbHistogramMetric : public TbbPerformanceMetric {
 public:
  explicit TbbHistogramMetric(const std::string& name,
                              const std::vector<double>& buckets = {})
      : TbbPerformanceMetric(name, MetricType::kHistogram),
        buckets_(buckets.empty() ? GetDefaultBuckets() : buckets),
        bucket_counts_(buckets_.size()) {
    // 初始化桶计数器
    for (auto& count : bucket_counts_) {
      count.store(0, std::memory_order_release);
    }
  }

  void Observe(double value) {
    Record(value);

    // 更新直方图桶
    for (size_t i = 0; i < buckets_.size(); ++i) {
      if (value <= buckets_[i]) {
        bucket_counts_[i].fetch_add(1, std::memory_order_relaxed);
        break;
      }
    }
  }

  // 获取直方图数据
  std::vector<std::pair<double, uint64_t>> GetHistogramData() const {
    std::vector<std::pair<double, uint64_t>> data;
    data.reserve(buckets_.size());

    for (size_t i = 0; i < buckets_.size(); ++i) {
      data.emplace_back(buckets_[i],
                        bucket_counts_[i].load(std::memory_order_acquire));
    }

    return data;
  }

 private:
  std::vector<double> buckets_;
  std::vector<std::atomic<uint64_t>> bucket_counts_;

  static std::vector<double> GetDefaultBuckets() {
    return {0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0};
  }
};

// 速率指标
class TbbRateMetric : public TbbPerformanceMetric {
 public:
  explicit TbbRateMetric(const std::string& name,
                         std::chrono::seconds window = std::chrono::seconds(60))
      : TbbPerformanceMetric(name, MetricType::kRate),
        window_size_(window),
        event_count_(0) {}

  void Mark(uint64_t count = 1) {
    event_count_.fetch_add(count, std::memory_order_relaxed);

    auto now = std::chrono::steady_clock::now();
    event_timestamps_.Push(now);

    // 计算当前速率
    double rate = CalculateRate();
    Record(rate);
  }

  double GetRate() const {
    return const_cast<TbbRateMetric*>(this)->CalculateRate();
  }

 private:
  std::chrono::seconds window_size_;
  std::atomic<uint64_t> event_count_;
  TbbRingBuffer<std::chrono::steady_clock::time_point> event_timestamps_{1000};

  double CalculateRate() {
    auto now = std::chrono::steady_clock::now();
    auto window_start = now - window_size_;

    // 计算窗口内的事件数量
    auto all_timestamps = event_timestamps_.GetAllData();
    uint64_t events_in_window = 0;

    for (const auto& timestamp : all_timestamps) {
      if (timestamp >= window_start) {
        events_in_window++;
      }
    }

    // 计算每秒速率
    double window_seconds = static_cast<double>(window_size_.count());
    return static_cast<double>(events_in_window) / window_seconds;
  }
};

// TBB原生的性能监控管理器
class TbbPerformanceMonitor {
 public:
  TbbPerformanceMonitor()
      : monitoring_arena_(tbb::info::default_concurrency()),
        comprehensive_observer_(),
        monitoring_enabled_(true) {
    // 启动监控任务
    StartMonitoringTasks();
  }

  ~TbbPerformanceMonitor() { Shutdown(); }

  // 注册指标
  template <typename MetricType>
  std::shared_ptr<MetricType> RegisterMetric(const std::string& name) {
    auto metric = std::make_shared<MetricType>(name);

    MetricMap::accessor accessor;
    if (metrics_.insert(accessor, name)) {
      accessor->second = metric;
      return metric;
    }

    // 如果指标已存在，尝试转换类型
    auto existing_metric =
        std::dynamic_pointer_cast<MetricType>(accessor->second);
    return existing_metric;
  }

  // 获取指标
  template <typename MetricType>
  std::shared_ptr<MetricType> GetMetric(const std::string& name) {
    MetricMap::const_accessor accessor;
    if (metrics_.find(accessor, name)) {
      return std::dynamic_pointer_cast<MetricType>(accessor->second);
    }
    return nullptr;
  }

  // 便捷方法：创建计数器
  std::shared_ptr<TbbCounterMetric> CreateCounter(const std::string& name) {
    return RegisterMetric<TbbCounterMetric>(name);
  }

  // 便捷方法：创建仪表
  std::shared_ptr<TbbGaugeMetric> CreateGauge(const std::string& name) {
    return RegisterMetric<TbbGaugeMetric>(name);
  }

  // 便捷方法：创建计时器
  std::shared_ptr<TbbTimerMetric> CreateTimer(const std::string& name) {
    return RegisterMetric<TbbTimerMetric>(name);
  }

  // 便捷方法：创建直方图
  std::shared_ptr<TbbHistogramMetric> CreateHistogram(
      const std::string& name, const std::vector<double>& buckets = {}) {
    auto metric = std::make_shared<TbbHistogramMetric>(name, buckets);

    MetricMap::accessor accessor;
    if (metrics_.insert(accessor, name)) {
      accessor->second = metric;
    }

    return metric;
  }

  // 便捷方法：创建速率指标
  std::shared_ptr<TbbRateMetric> CreateRate(
      const std::string& name,
      std::chrono::seconds window = std::chrono::seconds(60)) {
    auto metric = std::make_shared<TbbRateMetric>(name, window);

    MetricMap::accessor accessor;
    if (metrics_.insert(accessor, name)) {
      accessor->second = metric;
    }

    return metric;
  }

  // 获取所有指标名称
  std::vector<std::string> GetAllMetricNames() const {
    std::vector<std::string> names;
    names.reserve(metrics_.size());

    for (MetricMap::const_iterator it = metrics_.begin(); it != metrics_.end();
         ++it) {
      names.push_back(it->first);
    }

    return names;
  }

  // 获取系统性能快照
  struct SystemPerformanceSnapshot {
    TbbComprehensiveObserver::ComprehensiveMetrics tbb_metrics;
    std::chrono::steady_clock::time_point timestamp;

    // 自定义指标摘要
    struct MetricSummary {
      std::string name;
      MetricType type;
      double current_value;
      MetricStatistics statistics;
    };

    std::vector<MetricSummary> custom_metrics;
  };

  SystemPerformanceSnapshot GetPerformanceSnapshot() const {
    SystemPerformanceSnapshot snapshot;
    snapshot.tbb_metrics = comprehensive_observer_.GetComprehensiveMetrics();
    snapshot.timestamp = std::chrono::steady_clock::now();

    // 收集自定义指标
    for (MetricMap::const_iterator it = metrics_.begin(); it != metrics_.end();
         ++it) {
      SystemPerformanceSnapshot::MetricSummary summary;
      summary.name = it->first;
      summary.type = it->second->GetType();
      summary.statistics = it->second->GetStatistics();

      // 获取当前值（根据指标类型）
      switch (summary.type) {
        case MetricType::kCounter:
          if (auto counter =
                  std::dynamic_pointer_cast<TbbCounterMetric>(it->second)) {
            summary.current_value = counter->GetValue();
          }
          break;
        case MetricType::kGauge:
          if (auto gauge =
                  std::dynamic_pointer_cast<TbbGaugeMetric>(it->second)) {
            summary.current_value = gauge->GetValue();
          }
          break;
        case MetricType::kRate:
          if (auto rate =
                  std::dynamic_pointer_cast<TbbRateMetric>(it->second)) {
            summary.current_value = rate->GetRate();
          }
          break;
        default:
          summary.current_value = summary.statistics.avg_value;
          break;
      }

      snapshot.custom_metrics.push_back(summary);
    }

    return snapshot;
  }

  // 导出指标数据
  std::string ExportMetrics(const std::string& format = "json") const {
    if (format == "json") {
      return ExportToJson();
    } else if (format == "prometheus") {
      return ExportToPrometheus();
    }

    return "";
  }

  // 设置监控间隔
  void SetMonitoringInterval(std::chrono::milliseconds interval) {
    monitoring_interval_.store(interval, std::memory_order_release);
  }

  // 启用/禁用监控
  void EnableMonitoring(bool enable) {
    monitoring_enabled_.store(enable, std::memory_order_release);
  }

  // 重置所有指标
  void ResetAllMetrics() {
    for (MetricMap::iterator it = metrics_.begin(); it != metrics_.end();
         ++it) {
      it->second->Reset();
    }

    comprehensive_observer_.ResetAllMetrics();
  }

  // 删除指标
  bool RemoveMetric(const std::string& name) { return metrics_.erase(name); }

  // 获取监控统计信息
  struct MonitoringStats {
    size_t total_metrics;
    size_t active_metrics;
    uint64_t total_data_points;
    std::chrono::milliseconds monitoring_interval;
    bool monitoring_enabled;
  };

  MonitoringStats GetMonitoringStats() const {
    MonitoringStats stats;
    stats.total_metrics = metrics_.size();
    stats.active_metrics = 0;
    stats.total_data_points = 0;
    stats.monitoring_interval =
        monitoring_interval_.load(std::memory_order_acquire);
    stats.monitoring_enabled =
        monitoring_enabled_.load(std::memory_order_acquire);

    for (MetricMap::const_iterator it = metrics_.begin(); it != metrics_.end();
         ++it) {
      auto metric_stats = it->second->GetStatistics();
      if (metric_stats.count > 0) {
        stats.active_metrics++;
      }
      stats.total_data_points += metric_stats.count;
    }

    return stats;
  }

  // 关闭监控
  void Shutdown() {
    monitoring_enabled_.store(false, std::memory_order_release);

    // 等待监控任务完成
    monitoring_task_group_.wait();
  }

 private:
  using MetricMap =
      tbb::concurrent_hash_map<std::string,
                               std::shared_ptr<TbbPerformanceMetric>>;

  MetricMap metrics_;
  tbb::task_arena monitoring_arena_;
  tbb::task_group monitoring_task_group_;

  TbbComprehensiveObserver comprehensive_observer_;

  std::atomic<std::chrono::milliseconds> monitoring_interval_{
      std::chrono::seconds(1)};
  std::atomic<bool> monitoring_enabled_;

  // 启动监控任务
  void StartMonitoringTasks() {
    // 系统指标收集任务
    monitoring_task_group_.run([this]() {
      while (monitoring_enabled_.load(std::memory_order_acquire)) {
        CollectSystemMetrics();

        auto interval = monitoring_interval_.load(std::memory_order_acquire);
        std::this_thread::sleep_for(interval);
      }
    });

    // 指标清理任务
    monitoring_task_group_.run([this]() {
      while (monitoring_enabled_.load(std::memory_order_acquire)) {
        CleanupOldMetrics();
        std::this_thread::sleep_for(std::chrono::minutes(5));
      }
    });
  }

  // 收集系统指标
  void CollectSystemMetrics() {
    if (!monitoring_enabled_.load(std::memory_order_acquire)) {
      return;
    }

    // 更新内置系统指标
    auto tbb_metrics = comprehensive_observer_.GetComprehensiveMetrics();

    // 创建或更新系统指标
    auto cpu_gauge = GetMetric<TbbGaugeMetric>("system.cpu.utilization");
    if (!cpu_gauge) {
      cpu_gauge = CreateGauge("system.cpu.utilization");
    }

    auto memory_gauge = GetMetric<TbbGaugeMetric>("system.memory.usage");
    if (!memory_gauge) {
      memory_gauge = CreateGauge("system.memory.usage");
    }

    auto thread_gauge = GetMetric<TbbGaugeMetric>("system.threads.active");
    if (!thread_gauge) {
      thread_gauge = CreateGauge("system.threads.active");
    }

    // 更新指标值
    thread_gauge->SetValue(
        static_cast<double>(tbb_metrics.system_metrics.active_threads));

    // 可以添加更多系统指标...
  }

  // 清理旧指标数据
  void CleanupOldMetrics() {
    // 清理超过一定时间的指标数据
    // 这里可以实现数据保留策略
  }

  // 导出为JSON格式
  std::string ExportToJson() const {
    std::string json = "{";
    json +=
        "  \"timestamp\": \"" +
        std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
                           std::chrono::steady_clock::now().time_since_epoch())
                           .count()) +
        "\",";
    json += "  \"metrics\": {";

    bool first = true;
    for (MetricMap::const_iterator it = metrics_.begin(); it != metrics_.end();
         ++it) {
      if (!first) json += ",";
      first = false;

      json += "    \"" + it->first + "\": {";
      json += "      \"type\": \"" + MetricTypeToString(it->second->GetType()) +
              "\",";

      auto stats = it->second->GetStatistics();
      json += "      \"statistics\": {";
      json += "        \"count\": " + std::to_string(stats.count) + ",";
      json += "        \"min\": " + std::to_string(stats.min_value) + ",";
      json += "        \"max\": " + std::to_string(stats.max_value) + ",";
      json += "        \"avg\": " + std::to_string(stats.avg_value) + "";
      json += "      }";
      json += "    }";
    }

    json += "  }";
    json += "}";

    return json;
  }

  // 导出为Prometheus格式
  std::string ExportToPrometheus() const {
    std::string prometheus;

    for (MetricMap::const_iterator it = metrics_.begin(); it != metrics_.end();
         ++it) {
      std::string metric_name = it->first;
      std::replace(metric_name.begin(), metric_name.end(), '.', '_');

      auto stats = it->second->GetStatistics();

      prometheus += "# HELP " + metric_name + " " + it->first + "";
      prometheus += "# TYPE " + metric_name + " " +
                    MetricTypeToPrometheusType(it->second->GetType()) + "";
      prometheus += metric_name + "_count " + std::to_string(stats.count) + "";
      prometheus +=
          metric_name + "_sum " + std::to_string(stats.sum_value) + "";
      prometheus += "";
    }

    return prometheus;
  }

  // 指标类型转字符串
  static std::string MetricTypeToString(MetricType type) {
    switch (type) {
      case MetricType::kCounter:
        return "counter";
      case MetricType::kGauge:
        return "gauge";
      case MetricType::kHistogram:
        return "histogram";
      case MetricType::kTimer:
        return "timer";
      case MetricType::kRate:
        return "rate";
      default:
        return "unknown";
    }
  }

  // 指标类型转Prometheus类型
  static std::string MetricTypeToPrometheusType(MetricType type) {
    switch (type) {
      case MetricType::kCounter:
        return "counter";
      case MetricType::kGauge:
        return "gauge";
      case MetricType::kHistogram:
        return "histogram";
      case MetricType::kTimer:
        return "histogram";
      case MetricType::kRate:
        return "gauge";
      default:
        return "untyped";
    }
  }
};

// 全局性能监控管理器
class GlobalPerformanceMonitor {
 public:
  static TbbPerformanceMonitor& GetInstance() {
    static TbbPerformanceMonitor instance;
    return instance;
  }

  // 便捷的指标创建方法
  template <typename MetricType>
  static std::shared_ptr<MetricType> CreateMetric(const std::string& name) {
    return GetInstance().RegisterMetric<MetricType>(name);
  }

  template <typename MetricType>
  static std::shared_ptr<MetricType> GetMetric(const std::string& name) {
    return GetInstance().GetMetric<MetricType>(name);
  }

 private:
  GlobalPerformanceMonitor() = default;
};
}  // namespace itbb

#endif  // ITBB_MONITORING_TBB_PERFORMANCE_MONITOR_H_
